package com.zch.rpc.core.provider;

import com.zch.rpc.core.annotation.RpcPath;
import com.zch.rpc.core.annotation.RpcService;
import com.zch.rpc.core.enums.ProtocolEnum;
import com.zch.rpc.core.exception.RpcException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @Auther: zch
 * @Date: 2019/1/5 18:29
 * @Description:
 */
public class SpringRpcProviderFactory extends RpcProviderFactory implements ApplicationContextAware, InitializingBean {
    private ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
        String protocoal = getProtocol();

        if (StringUtils.isEmpty(protocoal) || protocoal.equals(ProtocolEnum.DUBBO.getValue())) {
            Map<String, Object> serviceMap = context.getBeansWithAnnotation(RpcService.class);
            if (!CollectionUtils.isEmpty(serviceMap)) {
                serviceMap.forEach((k, v) -> {
                    RpcService rpcService = v.getClass().getAnnotation(RpcService.class);
                    String key = makeServiceKey(rpcService.interfaceClass().getName(), rpcService.groupId(), rpcService.version());
                    putService(key, v);
                });
            }
        } else if (protocoal.equals(ProtocolEnum.RESTFUL.getValue())) {
            Map<String, Object> serviceMap = context.getBeansWithAnnotation(RpcPath.class);
            if (!CollectionUtils.isEmpty(serviceMap)) {
                serviceMap.forEach((k, v) -> {
                    Method[] methods = v.getClass().getMethods();
                    for (Method method : methods) {
                        RpcPath methodPath = method.getAnnotation(RpcPath.class);
                        if (methodPath != null) {
                            String url = methodPath.value();
                            if (StringUtils.isEmpty(url)) {
                                throw new RpcException("methd rpcPath value can not empty");
                            }
                            RpcPath beanPath = method.getDeclaringClass().getAnnotation(RpcPath.class);
                            if (beanPath != null) {
                                if (!StringUtils.isEmpty(beanPath.value())) {
                                    url = beanPath.value().concat(url);
                                }
                            }
                            HttpRequestMethodInfo httpRequestMethodInfo = new HttpRequestMethodInfo();
                            httpRequestMethodInfo.setBean(v);
                            httpRequestMethodInfo.setMethod(method);
                            httpRequestMethodInfo.setBeanName(k);
                            putService(url, httpRequestMethodInfo);
                        }
                    }
                });
            }
        }
    }

    //容器启动好后开始初始化rpc服务
    @PostConstruct
    private void initService() throws Exception {

        //startServer();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        super.validConfig();
        super.startServer();
    }
}
